package com.sanbi.common.util;

import org.springframework.util.Base64Utils;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Base64Util {

    public static String encode(String data) {
        return Base64Utils.encodeToString(data.getBytes(StandardCharsets.UTF_8));
    }

    public static String decode(String data) {
        return new String(decode(data.toCharArray()));
    }

    /**
     * 解析为字节数组
     *
     * @param str 解析字符串
     * @return 字节数组
     */
    public static byte[] parseAsByteArray(String str) {
        Base64.Decoder decoder = Base64.getDecoder();
        return decoder.decode(str);
    }

    private static byte[] decode(char[] data) {
        int tempLen = data.length;
        for (int ix = 0; ix < data.length; ix++) {
            if ((data[ix] > 255) || codes[data[ix]] < 0) {
                --tempLen; // ignore non-valid chars and padding
            }
        }
        // calculate required length:
        // -- 3 bytes for every 4 valid base64 chars
        // -- plus 2 bytes if there are 3 extra base64 chars,
        // or plus 1 byte if there are 2 extra.
        int len = (tempLen / 4) * 3;
        if ((tempLen % 4) == 3) {
            len += 2;
        }
        if ((tempLen % 4) == 2) {
            len += 1;
        }
        byte[] out = new byte[len];
        int shift = 0; // # of excess bits stored in accum
        int accum = 0; // excess bits
        int index = 0;
        // we now go through the entire array (NOT using the 'tempLen' value)
        for (int ix = 0; ix < data.length; ix++) {
            int value = (data[ix] > 255) ? -1 : codes[data[ix]];
            if (value >= 0) {  // skip over non-code
                accum <<= 6; // bits shift up by 6 each time thru
                shift += 6; // loop, with new bits being put in
                accum |= value; // at the bottom.
                if (shift >= 8) {  // whenever there are 8 or more shifted in,
                    shift -= 8; // write them out (from the top, leaving any
                    out[index++] = // excess at the bottom for next iteration.
                            (byte) ((accum >> shift) & 0xff);
                }
            }
        }
        // if there is STILL something wrong we just have to throw up now!
        if (index != out.length) {
            throw new Error("Miscalculated data length (wrote " + index
                    + " instead of " + out.length + ")");
        }
        return out;
    }

    private static char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray();
    private static byte[] codes = new byte[256];
    static {
        for (int i = 0; i < 256; i++) {
            codes[i] = -1;
            // LoggerUtil.debug(i + "&" + codes[i] + " ");
        }
        for (int i = 'A'; i <= 'Z'; i++) {
            codes[i] = (byte) (i - 'A');
            // LoggerUtil.debug(i + "&" + codes[i] + " ");
        }
        for (int i = 'a'; i <= 'z'; i++) {
            codes[i] = (byte) (26 + i - 'a');
            // LoggerUtil.debug(i + "&" + codes[i] + " ");
        }
        for (int i = '0'; i <= '9'; i++) {
            codes[i] = (byte) (52 + i - '0');
            // LoggerUtil.debug(i + "&" + codes[i] + " ");
        }
        codes['+'] = 62;
        codes['/'] = 63;
    }

    private static byte[] readBytes(File file) {
        byte[] b = null;
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             InputStream fis = new FileInputStream(file);
             InputStream is = new BufferedInputStream(fis);
        ) {
            int count = 0;
            byte[] buf = new byte[16384];
            while ((count = is.read(buf)) != -1) {
                if (count > 0) {
                    baos.write(buf, 0, count);
                }
            }
            b = baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return b;
    }

    public static void main(String[] args) {
        String appId="16819832118086830";
        String securityKey="Pagsmile_sk_7588b3bf50a3c3f126051f638897962c13053ca0b7dc5aeba21883da6503cf59";
        String initStr=String.format("%s:%s",appId,securityKey);
        System.out.println("initStr: "+initStr);

        String encodeStr=encode(initStr);
        System.out.println("encodeStr: "+encodeStr);

        String decodeStr=decode(encodeStr);
        System.out.println("decodeStr: "+decodeStr);
    }
}
